package com.px.baolaiapi.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.px.mbg.mapper.SequenceNumberMapper;
import com.px.mbg.model.SequenceNumber;
import com.px.baolaiapi.service.ISequenceNumberService;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <p>
 * 序号信息 服务实现类
 * </p>
 *
 * @author 品讯科技
 * @since 2022-03-17
 */
@Service
public class SequenceNumberServiceImpl extends ServiceImpl<SequenceNumberMapper, SequenceNumber> implements ISequenceNumberService {

    static final Lock lock = new ReentrantLock();

    /**
     * 创建序列号
     *
     * @param pre     前缀名
     * @param pattern 日期格式
     * @param bit     保留多少位序列号
     * @return {@link String}
     */
    @Override
    public String createSequenceNumber(String pre, String pattern, int bit) {
        lock.lock();
        try {
            LocalDateTime now = LocalDateTime.now();
            String format = now.format(DateTimeFormatter.ofPattern(pattern));
            SequenceNumber sequenceNumber = this.getOne(new QueryWrapper<SequenceNumber>().lambda().eq(SequenceNumber::getCode, pre).eq(SequenceNumber::getDateStr, format));
            int sNo = 1;
            if (ObjectUtil.isNotEmpty(sequenceNumber)) {
                sNo = sequenceNumber.getSequenceNo() + 1;
                sequenceNumber.setSequenceNo(sNo);
                this.updateById(sequenceNumber);
            } else {
                sequenceNumber = new SequenceNumber();
                sequenceNumber.setCode(pre);
                sequenceNumber.setDateStr(format);
                sequenceNumber.setSequenceNo(sNo);
                this.save(sequenceNumber);
            }
            return pre + format + String.format("%0" + bit + "d", sNo);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return "";
    }

    /**
     * 创建序列号-无前缀
     *
     * @param pattern 日期格式
     * @param bit     保留多少位序列号
     * @return {@link String}
     */
    @Override
    public String createSequenceNumberNop(String pre,String pattern, int bit) {
        lock.lock();
        try {

            LocalDateTime now = LocalDateTime.now();
            String format = now.format(DateTimeFormatter.ofPattern(pattern));
            //SequenceNumber sequenceNumber = this.getOne(new QueryWrapper<SequenceNumber>().lambda().eq(SequenceNumber::getCode, pre).eq(SequenceNumber::getDateStr, format));
            List<SequenceNumber> sequenceNumberList = this.list(new QueryWrapper<SequenceNumber>().lambda().eq(SequenceNumber::getCode, pre).eq(SequenceNumber::getDateStr, format));
            SequenceNumber sequenceNumber = null;
            if (sequenceNumberList.size() > 0) {
                sequenceNumber = sequenceNumberList.get(0);
            }
            int sNo = 1;
            if (ObjectUtil.isNotEmpty(sequenceNumber)) {
                sNo = sequenceNumber.getSequenceNo() + 1;
                sequenceNumber.setSequenceNo(sNo);
                this.updateById(sequenceNumber);
            } else {
                sequenceNumber = new SequenceNumber();
                sequenceNumber.setCode(pre);
                sequenceNumber.setDateStr(format);
                sequenceNumber.setSequenceNo(sNo);
                this.save(sequenceNumber);
            }
            return format + String.format("%0" + bit + "d", sNo);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return "";
    }

    /**
     * 创建序列号 有前缀和横杠
     *
     * @param pre     前缀名
     * @param pattern 日期格式
     * @param bit     保留多少位序列号
     * @param rod     日期与序列号中间需要增加的字符，默认为"-"
     * @return String
     */
    @Override
    public String createSequenceNumberRod(String pre, String pattern, int bit, String rod) {
        String sequenceNumberString = null; // 用于存储生成的序列号字符串
        lock.lock();
        try {
            LocalDateTime now = LocalDateTime.now();
            String format = DateTimeFormatter.ofPattern(pattern).format(now);
            SequenceNumber sequenceNumber = this.getOne(new QueryWrapper<SequenceNumber>().lambda()
                    .eq(SequenceNumber::getCode, pre)
                    .eq(SequenceNumber::getDateStr, format));

            int sNo = 1;
            if (sequenceNumber != null) {
                sNo = sequenceNumber.getSequenceNo() + 1;
                sequenceNumber.setSequenceNo(sNo);
                this.updateById(sequenceNumber);
            } else {
                sequenceNumber = new SequenceNumber();
                sequenceNumber.setCode(pre);
                sequenceNumber.setDateStr(format);
                sequenceNumber.setSequenceNo(sNo);
                this.save(sequenceNumber);
            }
            Random random = new Random();
            // 生成的随机数范围是0到9000，然后加1000以调整到1000到9999的范围
            Integer randomNumber = random.nextInt(9000) + 1000; // 9000是9999-1000，确保上限是9999
            // 使用String.format生成格式化的序列号，并与前缀、日期和分隔符拼接
            sequenceNumberString = pre + format +"-"+ randomNumber + (rod != null && !rod.isEmpty() ? rod : "-") + String.format("%0" + bit + "d", sNo);

        } catch (Exception e) {
            // 在异常发生时，生成一个随机序列号
            Random random = new Random();
            Integer randomNumber = random.nextInt(9000) + 1000;
            sequenceNumberString = pre + "-" + randomNumber;
            e.printStackTrace(); // 打印异常信息，便于调试
        } finally {
            lock.unlock();
        }
        return sequenceNumberString; // 返回生成的序列号字符串
    }
    /**
     * 返回序列号
     *
     * @param pre 前缀名
     * @param bit 保留多少位序列号
     * @return {@link String}
     */
    @Override
    public String getSequenceNumber(String pre, int bit) {
        lock.lock();
        try {
            SequenceNumber sequenceNumber = this.getOne(new QueryWrapper<SequenceNumber>().lambda().eq(SequenceNumber::getCode, pre));
            int sNo = 1;
            if (ObjectUtil.isNotEmpty(sequenceNumber)) {
                sNo = sequenceNumber.getSequenceNo() + 1;
                sequenceNumber.setSequenceNo(sNo);
                this.updateById(sequenceNumber);
            }else {
                Random random = new Random();
                Integer randomNumber = random.nextInt(9000) + 1000;
                return  randomNumber.toString();
            }

            return String.format("%0" + bit + "d", sNo);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return "0001";
    }
}
